home *** CD-ROM | disk | FTP | other *** search
/ Stone Design / Stone Design.iso / Stone_Friends / NeXT-Icons / next-icon@gun.com / FAQ / TransparentGIFs.rtfd / transgif.pl < prev    next >
Encoding:
Perl Script  |  1995-01-01  |  3.9 KB  |  122 lines

  1. #!/usr/local/export/bin/perl
  2. ## Make a gif "transparent"
  3. ##
  4. ## Jeffrey Friedl
  5. ## jfriedl@omrongw.wg.omron.co.jp
  6. ## 15 July 1994
  7. ##
  8. ## I wrote this because people ask for something like this all the time.
  9. ## I just learned the format of GIFs a week ago, so this will likely be
  10. ## lacking in many respects.
  11. ##
  12. ## Usage:
  13. ##
  14. ##   transgif [colornum] regular.gif > transparent.gif
  15. ## or
  16. ##   cat regular.gif | transgif [colornum] transparent.gif
  17. ##
  18. ## COLORNUM is the index of the color entry to make transparent, and
  19. ## defaults to zero. For those that like the looks of it, you can put
  20. ## a leading '-'.
  21. ##
  22. ## Idea for the future: let the color be defined as R-G-B and select the
  23. ## closest color from the colormap and use that.
  24. ##
  25.  
  26. $color = 0;
  27. if (@ARGV && $ARGV[0] =~ m/^-?(\d+)/) {
  28.     $color = $1;
  29.     shift;
  30. }
  31.  
  32. die "too many args; usage: $0 [colornum] [file]\n" if @ARGV > 1;
  33. if (@ARGV == 0) {
  34.     &giftrans(*STDIN, *STDOUT, $color);
  35. } else {
  36.     open(INPUT,  $file =shift) || die "$0: couldn't open [$file] for input\n";
  37.     &giftrans(*INPUT, *STDOUT, $color);
  38.     close(INPUT);
  39. }
  40.  
  41. ##
  42. ## Given indirect references to two filehandles, pass the file from
  43. ## one to the other, changing nothing unless it's a GIF that we know
  44. ## how to deal with, and if so do so.
  45. ##
  46. ## This is written rather verbosely for the sake of clarity... speed not
  47. ## much of an issue for something like this, and the difference is minimal
  48. ## anyway.
  49. ##
  50. sub giftrans
  51. {
  52.     local(*IN, *OUT, $color) = @_;
  53.     $color = 0 if !defined $color;
  54.     local($header, $color_table, $nextblock, $buffer) = ('') x 4;
  55.  
  56.     ## The header looks like:
  57.     ##   byte 0 - 5:  "GIF89a" or "GIF87a"
  58.     ##   byte 6, 7:   width  (low order first)
  59.     ##   byte 8, 9:   height (low order first)
  60.     ##   byte 10:     various flags
  61.     ##   byte 11:     background color index
  62.     ##   byte 12:     aspect ratio
  63.     sysread(IN, $header, 13) || die "sysread header";
  64.     substr($header, 0, 6) = 'GIF89a' if substr($header,0,6) eq 'GIF87a';
  65.     print OUT $header;
  66.  
  67.     if (substr($header, 0, 6) ne 'GIF89a') {
  68.     print STDERR "don't know input filetype, passing unchanged\n";
  69.     } else {
  70.     ##
  71.     ## Look at flags:
  72.     ##   High bit is global colormap indicator.
  73.     ##   Value_in_next_three_bits + 1 == number of bits per pixel.
  74.     ##   Next bit indicates if color map is sorted by importance.
  75.     ##   (1 + 2 ** (Value_in_final_three_bits + 1)) == size of colormap.
  76.     ##
  77.     local($flags) = ord(substr($header, 10, 1));
  78.     local($has_global_colormap) = $flags & 0x80;
  79.  
  80.     ## Copy over the colormap if need be.
  81.     if ($has_global_colormap)
  82.     {
  83.         local($bits_per_color) = 1 + ($flags & 0x07);
  84.         local($color_tbl_size) = 3 * (1 << $bits_per_color);
  85.  
  86.         sysread(IN, $color_table, $color_tbl_size) || die "sysread color";
  87.         print OUT $color_table;
  88.     }
  89.  
  90.     ##
  91.     ## The next 8 bytes will either be an already-there graphic-extension
  92.     ## block, or something else that we'll not care about. In the latter
  93.     ## case, we'll add a graphic-extension block saying "color such-and-
  94.     ## such is transparent". If there's already one there, we'll just
  95.     ## ensure that it says that.
  96.     ##
  97.     sysread(IN, $nextblock, 8) || die "sysread nextblock";
  98.     local($extension, $label) = unpack('CC', $nextblock);
  99.     ## If extension is 0x21 and label is 0xf9, that's the magic tha means
  100.     ## there's already a graphic extension there.
  101.     if ($extension == 0x21 && $label == 0xf9) {
  102.         substr($nextblock, 3, 1) = pack('C', 1|substr($nextblock, 3, 1));
  103.         substr($nextblock, 6, 1) = pack('C', $color);
  104.     } else {
  105.         print OUT pack('CCC CCCC C',
  106.         0x21,  ## magic: "Extension Introducer"
  107.         0xf9,  ## magic: "Graphic Control Label"
  108.            4,  ## bytes in block (between here and terminator)
  109.         0x01,  ## indicates that 'transparet index' is given
  110.         0, 0,  ## delay time.
  111.           $color,  ## index of "transparent" color.
  112.         0x00); ## terminator.
  113.     }
  114.     print OUT $nextblock;
  115.     }
  116.  
  117.     ## Now just pass the rest of the file over unchanged.
  118.  
  119.     print OUT $buffer while sysread(IN, $buffer, 4096);
  120.     close(IN);
  121.     close(OUT);
  122. }